BeanPostProcessor
是Spring中参与Bean生命周期定制非常重要的一个手段,上文分析过,其执行有两个时机
一前:Bean自动注入之后,自定义初始化方法调用前
一后:自定义方法调用之后
Spring中很多重要的特性利用了BeanPostProcessor
达成,毕竟,算来算去,Spring中整个Bean的生命周期已经足够复杂了,如果每加一个功能就要在生命周期上做文章,只会增加复杂度,而BeanPostProcessor
则是Spring提供的一种扩展方式。与其相对的,一般用户用的可能较少的BeanFactoryPostProcessor
是针对整个容器初始化完成后提供定制化功能的扩展,我们也要观察一下。观察的主要内容是主要实现类及其作用。
BeanFactoryPostProcessor 它的调用,在org.springframework.context.support.AbstractApplicationContext#refresh.564行
。
其接口及其简单:一个简单的函数式接口。
1 2 3 4 @FunctionalInterface public interface BeanFactoryPostProcessor { void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException ; }
这意味着,在容器创建后,我们能够向其中设置任何内容,也可以利用容器刚刚创建这个时机,来做一些时机上再容器全局的一些事情。
具体来说,有这么几类
修改现有容器配置
AbstractDependsOnBeanFactoryPostProcessor
、CacheManagerEntityManagerFactoryDependsOnPostProcessor
。强制为某些Bean显式设置依赖关系,使得不满足依赖时容器无法启动。这在自动配时会有用
CustomScopeConfigurer
,添加自定义scope,这在WebSocketMessageBrokerConfigurationSupport
有使用
CustomEditorConfigurer
,注册一些自定义的PropertyEditor
LazyInitializationBeanFactoryPostProcessor
,它将容器中没有指定延迟加载属性的bean定义,除以下条件的bean设置为延迟加载
SmartInitializingSingleton
类型
AopInfrastructureBean
类型
TaskScheduler
类型
ScheduledExecutorService
类型
被@Scheduled
或Schedules
注解的类
向容器中添加Bean
ServletComponentRegisteringPostProcessor
,它创建了一个Servlet环境,注册了必要的Bean
EventListenerMethodProcessor
,它配合SmartInitializingSingleton
,实现了@EventListener
注解
在容器初始化完成后,获取并持有了容器的EventListenerFactory
、容器本身
在单例Bean初始化完成后,检测带有@Component
的Bean内部是否有@EventListener
注解的方法,如果有,则使用上一步持有的EventListenerFactory
将该方法创建为一个ApplicationListener
实例,然后注入容器
一些全局开关
AspectJWeavingEnabler
,开启AspectJ。
BeanPostProcessor 它的执行时机,有两个:Bean创建后,实例化前;Bean实例化后。
1 2 3 4 5 6 7 8 9 10 11 public interface BeanPostProcessor { default Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { return bean; } default Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { return bean; } }
下面是主要实现
xxxAware
ApplicationContextAwareProcessor
,在Bean初始化之前,调用了如下接口的setxxx方法
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ApplicationContextAware
ApplicationStartupAware
BootstrapContextAwareProcessor
,在Bean初始化之前,调用了如下接口的setxxx方法
WebApplicationContextServletContextAwareProcessor
,在Bean初始化之前,调用了如下接口的setxxx方法
ServletContextAware
ServletConfigAware
ConfigurationPropertiesBindingPostProcessor 它将环境中的属性绑定到@ConfigurationProperties
注解到的类上。比如
1 2 3 4 5 @ConfigurationProperties(prefix = "aliyun" ) class AliyunConfig { lateinit var accessKey: String lateinit var secretKey: String }
它能够将配置中的如下属性注入对象
1 2 aliyun.access-key =xxxx aliyun.secret-key =xxx
来看看该类的源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProcessor , PriorityOrdered , ApplicationContextAware , InitializingBean { private ApplicationContext applicationContext; private BeanDefinitionRegistry registry; private ConfigurationPropertiesBinder binder; @Override public void setApplicationContext (ApplicationContext applicationContext) throws BeansException { this .applicationContext = applicationContext; } @Override public void afterPropertiesSet () throws Exception { this .registry = (BeanDefinitionRegistry) this .applicationContext.getAutowireCapableBeanFactory(); this .binder = ConfigurationPropertiesBinder.get(this .applicationContext); } @Override public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { bind(ConfigurationPropertiesBean.get(this .applicationContext, bean, beanName)); return bean; } private void bind (ConfigurationPropertiesBean bean) { if (bean == null || hasBoundValueObject(bean.getName())) { return ; } Assert.state(bean.getBindMethod() == BindMethod.JAVA_BEAN, "错误信息" ); this .binder.bind(bean); } }
理解它的关键,在于理解Spring的绑定机制,该机制有点复杂,不是一两句能说清的。简单来说,就是将一堆属性绑定到指定的领域模型。我们只简单地看一下上面涉及到的两个类。具体的,下一篇文章再来看。
ConfigurationPropertiesBean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public final class ConfigurationPropertiesBean { private final String name; private final Object instance; private final ConfigurationProperties annotation; private final Bindable<?> bindTarget; private final BindMethod bindMethod; private ConfigurationPropertiesBean (String name, Object instance, ConfigurationProperties annotation, Bindable<?> bindTarget) { this .name = name; this .instance = instance; this .annotation = annotation; this .bindTarget = bindTarget; this .bindMethod = BindMethod.forType(bindTarget.getType().resolve()); } public static ConfigurationPropertiesBean get (ApplicationContext applicationContext, Object bean, String beanName) { Method factoryMethod = findFactoryMethod(applicationContext, beanName); return create(beanName, bean, bean.getClass(), factoryMethod); } private static ConfigurationPropertiesBean create (String name, Object instance, Class<?> type, Method factory) { ConfigurationProperties annotation = findAnnotation(instance, type, factory, ConfigurationProperties.class); if (annotation == null ) { return null ; } Validated validated = findAnnotation(instance, type, factory, Validated.class); Annotation[] annotations = (validated != null ) ? new Annotation[] { annotation, validated } : new Annotation[] { annotation }; ResolvableType bindType = (factory != null ) ? ResolvableType.forMethodReturnType(factory) : ResolvableType.forClass(type); Bindable<Object> bindTarget = Bindable.of(bindType).withAnnotations(annotations); if (instance != null ) { bindTarget = bindTarget.withExistingValue(instance); } return new ConfigurationPropertiesBean(name, instance, annotation, bindTarget); } }
对Bindable
和BindMethod
,可能有一些陌生,暂且不管,后面专门写文章介绍它
ConfigurationPropertiesBean
中包含的内容:目标bean实例、ConfigurationProperties
注解、绑定目标、绑定方式
该类为绑定做准备
ConfigurationPropertiesBinder 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 class ConfigurationPropertiesBinder { private static final String BEAN_NAME = "org.springframework.boot.context.internalConfigurationPropertiesBinder" ; private static final String VALIDATOR_BEAN_NAME = EnableConfigurationProperties.VALIDATOR_BEAN_NAME; ConfigurationPropertiesBinder(ApplicationContext applicationContext) { this .applicationContext = applicationContext; this .propertySources = new PropertySourcesDeducer(applicationContext).getPropertySources(); this .configurationPropertiesValidator = getConfigurationPropertiesValidator(applicationContext); this .jsr303Present = ConfigurationPropertiesJsr303Validator.isJsr303Present(applicationContext); } static ConfigurationPropertiesBinder get (BeanFactory beanFactory) { return beanFactory.getBean(BEAN_NAME, ConfigurationPropertiesBinder.class); } BindResult<?> bind(ConfigurationPropertiesBean propertiesBean) { Bindable<?> target = propertiesBean.asBindTarget(); ConfigurationProperties annotation = propertiesBean.getAnnotation(); BindHandler bindHandler = getBindHandler(target, annotation); return getBinder().bind(annotation.prefix(), target, bindHandler); } private <T> BindHandler getBindHandler (Bindable<T> target, ConfigurationProperties annotation) { List<Validator> validators = getValidators(target); BindHandler handler = getHandler(); handler = new ConfigurationPropertiesBindHander(handler); if (annotation.ignoreInvalidFields()) { handler = new IgnoreErrorsBindHandler(handler); } if (!annotation.ignoreUnknownFields()) { UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter(); handler = new NoUnboundElementsBindHandler(handler, filter); } if (!validators.isEmpty()) { handler = new ValidationBindHandler(handler, validators.toArray(new Validator[0 ])); } for (ConfigurationPropertiesBindHandlerAdvisor advisor : getBindHandlerAdvisors()) { handler = advisor.apply(handler); } return handler; } private List<Validator> getValidators (Bindable<?> target) { List<Validator> validators = new ArrayList<>(3 ); if (this .configurationPropertiesValidator != null ) { validators.add(this .configurationPropertiesValidator); } if (this .jsr303Present && target.getAnnotation(Validated.class) != null ) { validators.add(getJsr303Validator()); } if (target.getValue() != null && target.getValue().get() instanceof Validator) { validators.add((Validator) target.getValue().get()); } return validators; } private Binder getBinder () { if (this .binder == null ) { this .binder = new Binder(getConfigurationPropertySources(), getPropertySourcesPlaceholdersResolver(), getConversionServices(), getPropertyEditorInitializer(), null , ConfigurationPropertiesBindConstructorProvider.INSTANCE); } return this .binder; } }
最终还是委托给了Binder
进行调用,ConfigurationPropertiesBinder
只能算是一个代理,准备好绑定需要的组件,然后调用Binder
完成绑定
我们看到大量的从容器中获取绑定组件的方式,却没看到什么时候在容器中创建了该bean?实际上getBean()
方法的首次调用就完成了创建和返回两个操作
绑定包含了验证的过程,默认会使用两个验证器
ConfigurationPropertiesValidator
ConfigurationPropertiesJsr303Validator
支持JSR303验证规范的前提条件:同时存在如下三个类型的Bean
Validator
ValidatorFactory
GenericBootstrap
ApplicationListenerDetector ApplicationListenerDetector
,用于检测实现了ApplicationListener
的Bean,并将其注入容器和时间广播器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor , MergedBeanDefinitionPostProcessor { private final transient AbstractApplicationContext applicationContext; private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256 ); @Override public void postProcessMergedBeanDefinition (RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { if (ApplicationListener.class.isAssignableFrom(beanType)) { this .singletonNames.put(beanName, beanDefinition.isSingleton()); } } @Override public Object postProcessAfterInitialization (Object bean, String beanName) { if (bean instanceof ApplicationListener) { Boolean flag = this .singletonNames.get(beanName); if (Boolean.TRUE.equals(flag)) { this .applicationContext.addApplicationListener((ApplicationListener<?>) bean); } else if (Boolean.FALSE.equals(flag)) { this .singletonNames.remove(beanName); } } return bean; } @Override public void postProcessBeforeDestruction (Object bean, String beanName) { if (bean instanceof ApplicationListener) { try { ApplicationEventMulticaster multicaster = this .applicationContext.getApplicationEventMulticaster(); multicaster.removeApplicationListener((ApplicationListener<?>) bean); multicaster.removeApplicationListenerBean(beanName); } catch (IllegalStateException ex) { } } } }
AutowiredAnnotationBeanPostProcessor 可以以该类为入口,查看整个Spring自动注入的逻辑。首先其继承结构如下。
这就意味着有以下几个扩展点可以观察
获取到MergedBeanDefinition
之后的执行点(关于MergedBeanDefinition
在关于Bean的描述那篇文章讨论过,这里不再看)
调用点:AbstractAutowireCapableBeanFactory.java:1116行,applyMergedBeanDefinitionPostProcessors()方法
Bean的属性读取完成之后的执行点
调用点:AbstractAutowireCapableBeanFactory.java:1436行,polupateBean()方法
构建Bean实例时用于判断构造方法参数的执行点
调用点:AbstractAutowireCapableBeanFactory.java:1302行,determineConstructorsFromBeanPostProcessors()方法
实际上,该processor同时干预了字段注入、方法注入、构造器注入。
首先看其构造方法,可知,适用的注解有三个:@Autowired、@Value、@Inject
,最后一个是适配JSR330。
1 2 3 4 5 6 7 8 9 10 11 12 13 public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor , MergedBeanDefinitionPostProcessor { public AutowiredAnnotationBeanPostProcessor () { this .autowiredAnnotationTypes.add(Autowired.class); this .autowiredAnnotationTypes.add(Value.class); try { this .autowiredAnnotationTypes.add((Class<? extends Annotation>)ClassUtils.forName("javax.inject.Inject" , AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring" ); } catch (ClassNotFoundException ex) { } } }
然后看第一个扩展点:postProcessMergedBeanDefinition()
,与他相关的方法全部摆出来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 public void postProcessMergedBeanDefinition (RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null ); metadata.checkConfigMembers(beanDefinition); } private InjectionMetadata findAutowiringMetadata (String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { InjectionMetadata metadata = ... ... ... metadata = buildAutowiringMetadata(clazz); ... ... return metadata; } private InjectionMetadata buildAutowiringMetadata (final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this .autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null ) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return ; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return ; } MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return ; } if (method.getParameterCount() == 0 ) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0 , currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); } private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) { MergedAnnotations annotations = MergedAnnotations.from(ao); for (Class<? extends Annotation> type : this .autowiredAnnotationTypes) { MergedAnnotation<?> annotation = annotations.get(type); if (annotation.isPresent()) { return annotation; } } return null ; } protected boolean determineRequiredStatus (MergedAnnotation<?> ann) { return determineRequiredStatus((AnnotationAttributes) ann.asMap(mergedAnnotation -> new AnnotationAttributes(mergedAnnotation.getType()))); } protected boolean determineRequiredStatus (AnnotationAttributes ann) { return (!ann.containsKey(this .requiredParameterName) || this .requiredParameterValue == ann.getBoolean(this .requiredParameterName)); }
三个注解@Autowired、@Value、@Inject
,作用在字段或构造方法上都可以;甚至可以作用在静态字段和方法上,只不过会被忽略而已
作用在方法上时,该方法必须拥有参数,方法不应是setter方法
决定注入是否必须的条件:未指定required时默认为必须,否则指定什么就是什么
然后我们来看第二个扩展点:postProcessProperties()
,它是执行注入的地方
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); metadata.inject(bean, beanName, pvs); return pvs; } public void inject (Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this .checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this .injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { element.inject(target, beanName, pvs); } } } protected void inject (Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs) throws Throwable { if (this .isField) { Field field = (Field) this .member; ReflectionUtils.makeAccessible(field); field.set(target, getResourceToInject(target, requestingBeanName)); } else { ... ... try { Method method = (Method) this .member; ReflectionUtils.makeAccessible(method); method.invoke(target, getResourceToInject(target, requestingBeanName)); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
最后来看它是如何决定构造方法以干预实例创建的:determineCandidateConstructors()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeanCreationException { if (!this .lookupMethodsChecked.contains(beanName)) { if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) { Class<?> targetClass = beanClass; do { ReflectionUtils.doWithLocalMethods(targetClass, method -> { Lookup lookup = method.getAnnotation(Lookup.class); if (lookup != null ) { LookupOverride override = new LookupOverride(method, lookup.value()); RootBeanDefinition mbd = (RootBeanDefinition)this .beanFactory.getMergedBeanDefinition(beanName); mbd.getMethodOverrides().addOverride(override); } }); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); } this .lookupMethodsChecked.add(beanName); } candidateConstructors = this .candidateConstructorsCache.get(beanClass); if (candidateConstructors == null ) { Constructor<?>[] rawCandidates; rawCandidates = beanClass.getDeclaredConstructors(); List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length); Constructor<?> requiredConstructor = null ; Constructor<?> defaultConstructor = null ; Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass); int nonSyntheticConstructors = 0 ; for (Constructor<?> candidate : rawCandidates) { if (!candidate.isSynthetic()) { nonSyntheticConstructors++; } else if (primaryConstructor != null ) { continue ; } MergedAnnotation<?> ann = findAutowiredAnnotation(candidate); if (ann == null ) { Class<?> userClass = ClassUtils.getUserClass(beanClass); if (userClass != beanClass) { try { Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes()); ann = findAutowiredAnnotation(superCtor); } catch (NoSuchMethodException ex) { } } } if (ann != null ) { boolean required = determineRequiredStatus(ann); if (required) { requiredConstructor = candidate; } candidates.add(candidate); } else if (candidate.getParameterCount() == 0 ) { defaultConstructor = candidate; } } if (!candidates.isEmpty()) { ... ... candidateConstructors = candidates.toArray(new Constructor<?>[0 ]); } else if (rawCandidates.length == 1 && rawCandidates[0 ].getParameterCount() > 0 ) { candidateConstructors = new Constructor<?>[] {rawCandidates[0 ]}; } else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor}; } else if (nonSyntheticConstructors == 1 && primaryConstructor != null ) { candidateConstructors = new Constructor<?>[] {primaryConstructor}; } else { candidateConstructors = new Constructor<?>[0 ]; } this .candidateConstructorsCache.put(beanClass, candidateConstructors); } return (candidateConstructors.length > 0 ? candidateConstructors : null ); }
总结一下,AutowiredAnnotationBeanPostProcessor
做了以下事情
被@Autowired、@Value、@Inject
注解的字段,会注入对应类型的实例;对被注解的方法,会将方法的参数注入对应类型的实例
被@Lookup
注解的方法,返回值将不会去方法真是返回的,而是返回类型对应的容器内的Bean实例
RequiredAnnotationBeanPostProcessor
先说明:@Required
注解已经过时了,现在推荐的使用方式是使用构造器注入,或实现自定义的InitializingBean
。
其关键逻辑比较简单:检查被@Required
注解的字段,是否都已经找到值准备注入,如果这个时候还没有值,就会报违反“必须”的错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public PropertyValues postProcessPropertyValues (PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) { if (!shouldSkip(this .beanFactory, beanName)) { List<String> invalidProperties = new ArrayList<>(); for (PropertyDescriptor pd : pds) { if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) { invalidProperties.add(pd.getName()); } } if (!invalidProperties.isEmpty()) { throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName)); } } return pvs; } protected boolean shouldSkip (@Nullable ConfigurableListableBeanFactory beanFactory, String beanName) { if (beanFactory == null || !beanFactory.containsBeanDefinition(beanName)) { return false ; } BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); if (beanDefinition.getFactoryBeanName() != null ) { return true ; } Object value = beanDefinition.getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE); return (value != null && (Boolean.TRUE.equals(value) || Boolean.parseBoolean(value.toString()))); } protected boolean isRequiredProperty (PropertyDescriptor propertyDescriptor) { Method setter = propertyDescriptor.getWriteMethod(); return (setter != null && AnnotationUtils.getAnnotation(setter, getRequiredAnnotationType()) != null ); }
InitDestroyAnnotationBeanPostProcessor 它其实和AutowiredAnnotationBeanPostProcessor
类似,在BeanDefinition
准备好后查找@PostConstruct、@PreDestroy
,后在对应的时机调用查找好的方法。
首先是查找这些方法的点:postProcessMergedBeanDefinition()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public void postProcessMergedBeanDefinition (RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { LifecycleMetadata metadata = findLifecycleMetadata(beanType); metadata.checkConfigMembers(beanDefinition); } private LifecycleMetadata findLifecycleMetadata (Class<?> clazz) { ... ... return buildLifecycleMetadata(clazz); } private LifecycleMetadata buildLifecycleMetadata (final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this .initAnnotationType, this .destroyAnnotationType))) { return this .emptyLifecycleMetadata; } List<LifecycleElement> initMethods = new ArrayList<>(); List<LifecycleElement> destroyMethods = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<LifecycleElement> currInitMethods = new ArrayList<>(); final List<LifecycleElement> currDestroyMethods = new ArrayList<>(); ReflectionUtils.doWithLocalMethods(targetClass, method -> { if (this .initAnnotationType != null && method.isAnnotationPresent(this .initAnnotationType)) { LifecycleElement element = new LifecycleElement(method); currInitMethods.add(element); } if (this .destroyAnnotationType != null && method.isAnnotationPresent(this .destroyAnnotationType)) { currDestroyMethods.add(new LifecycleElement(method)); } }); initMethods.addAll(0 , currInitMethods); destroyMethods.addAll(currDestroyMethods); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this .emptyLifecycleMetadata : new LifecycleMetadata(clazz, initMethods, destroyMethods)); }
然后是@PostConstruct
的执行点:postProcessBeforeInitialization()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); ... ... metadata.invokeInitMethods(bean, beanName); ... ... return bean; } public void invokeInitMethods (Object target, String beanName) throws Throwable { Collection<LifecycleElement> checkedInitMethods = this .checkedInitMethods; Collection<LifecycleElement> initMethodsToIterate = (checkedInitMethods != null ? checkedInitMethods : this .initMethods); if (!initMethodsToIterate.isEmpty()) { for (LifecycleElement element : initMethodsToIterate) { element.invoke(target); } } }
最后是@PreDestroy
的执行点:postProcessBeforeDestruction()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Override public void postProcessBeforeDestruction (Object bean, String beanName) throws BeansException { LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); ... ... metadata.invokeDestroyMethods(bean, beanName); ... ... } public void invokeDestroyMethods (Object target, String beanName) throws Throwable { Collection<LifecycleElement> checkedDestroyMethods = this .checkedDestroyMethods; Collection<LifecycleElement> destroyMethodsToUse = (checkedDestroyMethods != null ? checkedDestroyMethods : this .destroyMethods); if (!destroyMethodsToUse.isEmpty()) { for (LifecycleElement element : destroyMethodsToUse) { element.invoke(target); } } }
从这个源码看来
被@PostConstruct、@PreDesctroy
注解的方法可以有多个,他们会依次执行
被它们注解的方法需要是无参的,就算有参,也不会给你传值
ScheduledAnnotationBeanPostProcessor
源码分析 大致描述一下它的工作原理:
在单例初始化完成后,或收到ContextRefreshEvent
事件后,该Processor
需要准备好,准备的内容包括初始化用于指定定时任务的Scheduler
,持有任务元数据的ScheduledTaskRegistrar
;
在实例初始化完成后,从容器中查找带有@Scheduled、@Schedules
注解的方法,解析定时参数,构建成任务,然后提交执行;
在单个实例销毁前,从缓存中删除该实例对应的定时任务
在容器销毁前,清空缓存的定时任务
然后,我们来看准备阶段和检测阶段的代码,结束阶段就忽略掉了。先是准备阶段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public ScheduledAnnotationBeanPostProcessor () { this .registrar = new ScheduledTaskRegistrar(); } public void onApplicationEvent (ContextRefreshedEvent event) { if (event.getApplicationContext() == this .applicationContext) { finishRegistration(); } } private void finishRegistration () { if (this .scheduler != null ) { this .registrar.setScheduler(this .scheduler); } if (this .beanFactory instanceof ListableBeanFactory) { Map<String, SchedulingConfigurer> beans = ((ListableBeanFactory) this .beanFactory).getBeansOfType(SchedulingConfigurer.class); List<SchedulingConfigurer> configurers = new ArrayList<>(beans.values()); AnnotationAwareOrderComparator.sort(configurers); for (SchedulingConfigurer configurer : configurers) { configurer.configureTasks(this .registrar); } } if (this .registrar.hasTasks() && this .registrar.getScheduler() == null ) { Assert.state(this .beanFactory != null , "BeanFactory must be set to find scheduler by type" ); try { this .registrar.setTaskScheduler(resolveSchedulerBean(this .beanFactory, TaskScheduler.class, false )); } catch (NoUniqueBeanDefinitionException ex) { try { this .registrar.setTaskScheduler(resolveSchedulerBean(this .beanFactory, TaskScheduler.class, true )); } catch (NoSuchBeanDefinitionException ex2) { } } catch (NoSuchBeanDefinitionException ex) { try { this .registrar.setScheduler(resolveSchedulerBean(this .beanFactory, ScheduledExecutorService.class, false )); } catch (NoUniqueBeanDefinitionException ex2) { try { this .registrar.setScheduler(resolveSchedulerBean(this .beanFactory, ScheduledExecutorService.class, true )); } catch (NoSuchBeanDefinitionException ex3) { } } catch (NoSuchBeanDefinitionException ex2) { } } } this .registrar.afterPropertiesSet(); }
然后来看检测阶段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 public Object postProcessAfterInitialization (Object bean, String beanName) { Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean); if (!this .nonAnnotatedClasses.contains(targetClass) && AnnotationUtils.isCandidateClass(targetClass, Arrays.asList(Scheduled.class, Schedules.class))) { Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (MethodIntrospector.MetadataLookup<Set<Scheduled>>) method -> { Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class); return (!scheduledMethods.isEmpty() ? scheduledMethods : null ); }); if (annotatedMethods.isEmpty()) { this .nonAnnotatedClasses.add(targetClass); } else { annotatedMethods.forEach((method, scheduledMethods) -> scheduledMethods.forEach(scheduled -> processScheduled(scheduled, method, bean))); } } return bean; } protected void processScheduled (Scheduled scheduled, Method method, Object bean) { try { Runnable runnable = createRunnable(bean, method); boolean processedSchedule = false ; Set<ScheduledTask> tasks = new LinkedHashSet<>(4 ); long initialDelay = scheduled.initialDelay(); String initialDelayString = scheduled.initialDelayString(); if (StringUtils.hasText(initialDelayString)) { Assert.isTrue(initialDelay < 0 , "Specify 'initialDelay' or 'initialDelayString', not both" ); if (this .embeddedValueResolver != null ) { initialDelayString = this .embeddedValueResolver.resolveStringValue(initialDelayString); } if (StringUtils.hasLength(initialDelayString)) { try { initialDelay = parseDelayAsLong(initialDelayString); } catch (RuntimeException ex) { } } } String cron = scheduled.cron(); if (StringUtils.hasText(cron)) { String zone = scheduled.zone(); if (this .embeddedValueResolver != null ) { cron = this .embeddedValueResolver.resolveStringValue(cron); zone = this .embeddedValueResolver.resolveStringValue(zone); } if (StringUtils.hasLength(cron)) { Assert.isTrue(initialDelay == -1 , "'initialDelay' not supported for cron triggers" ); processedSchedule = true ; if (!Scheduled.CRON_DISABLED.equals(cron)) { TimeZone timeZone; if (StringUtils.hasText(zone)) { timeZone = StringUtils.parseTimeZoneString(zone); } else { timeZone = TimeZone.getDefault(); } tasks.add(this .registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone)))); } } } if (initialDelay < 0 ) { initialDelay = 0 ; } long fixedDelay = scheduled.fixedDelay(); if (fixedDelay >= 0 ) { Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true ; tasks.add(this .registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay))); } String fixedDelayString = scheduled.fixedDelayString(); if (StringUtils.hasText(fixedDelayString)) { if (this .embeddedValueResolver != null ) { fixedDelayString = this .embeddedValueResolver.resolveStringValue(fixedDelayString); } if (StringUtils.hasLength(fixedDelayString)) { Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true ; try { fixedDelay = parseDelayAsLong(fixedDelayString); } catch (RuntimeException ex) { } tasks.add(this .registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay))); } } long fixedRate = scheduled.fixedRate(); if (fixedRate >= 0 ) { Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true ; tasks.add(this .registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay))); } String fixedRateString = scheduled.fixedRateString(); if (StringUtils.hasText(fixedRateString)) { if (this .embeddedValueResolver != null ) { fixedRateString = this .embeddedValueResolver.resolveStringValue(fixedRateString); } if (StringUtils.hasLength(fixedRateString)) { Assert.isTrue(!processedSchedule, errorMessage); processedSchedule = true ; try { fixedRate = parseDelayAsLong(fixedRateString); } catch (RuntimeException ex) { } tasks.add(this .registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay))); } } synchronized (this .scheduledTasks) { Set<ScheduledTask> regTasks = this .scheduledTasks.computeIfAbsent(bean, key -> new LinkedHashSet<>(4 )); regTasks.addAll(tasks); } } catch (IllegalArgumentException ex) { ... ... } }
至此,Processor
的任务结束了,我们来看看这些任务的执行逻辑,以ScheduledTaskRegistrar.scheduleFixedRateTask()
为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public ScheduledTask scheduleFixedRateTask (FixedRateTask task) { ScheduledTask scheduledTask = this .unresolvedTasks.remove(task); boolean newTask = false ; if (scheduledTask == null ) { scheduledTask = new ScheduledTask(task); newTask = true ; } if (this .taskScheduler != null ) { if (task.getInitialDelay() > 0 ) { Date startTime = new Date(this .taskScheduler.getClock().millis() + task.getInitialDelay()); scheduledTask.future = this .taskScheduler.scheduleAtFixedRate(task.getRunnable(), startTime, task.getInterval()); } else { scheduledTask.future = this .taskScheduler.scheduleAtFixedRate(task.getRunnable(), task.getInterval()); } } else { addFixedRateTask(task); this .unresolvedTasks.put(task, scheduledTask); } return (newTask ? scheduledTask : null ); } public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) { ScheduledExecutorService executor = getScheduledExecutor(); long initialDelay = startTime.getTime() - this .clock.millis(); try { return executor.scheduleAtFixedRate(errorHandlingTask(task, true ), initialDelay, period, TimeUnit.MILLISECONDS); } catch (RejectedExecutionException ex) { throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex); } }
定时器如何生效 定时器默认不生效,当需要使用时,通过@EnableScheduling
引入,其最终结果是向容器中声明了ScheduledAnnotationBeanPostProcessor
实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Target (ElementType.TYPE)@Retention (RetentionPolicy.RUNTIME)@Import (SchedulingConfiguration.class)@Documented public @interface EnableScheduling {} @Configuration (proxyBeanMethods = false )@Role (BeanDefinition.ROLE_INFRASTRUCTURE)public class SchedulingConfiguration { @Bean (name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) @Role (BeanDefinition.ROLE_INFRASTRUCTURE) public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor () { return new ScheduledAnnotationBeanPostProcessor(); } }
其它 还有两个非常重要的内容:BeanValidationPostProcessor
、AOP相关处理器,涉及内容较多,将单独来看,这里忽略。
总结 本文介绍了通过BeanPostProcessor
实现的几个关键内容:配置绑定类、事件监听器的侦测、自动注入的实现、初始化和销毁注解的实现、定时任务的实现等。